package com.material.demo.lyric;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import java.util.List;

/**
 * 无局部刷新
 * Created by pc on 2016/12/22.
 */

public class LyricView extends View implements ILyric {

    private static final String TAG = LyricView.class.getName();

    private final static int TYPE_NO_LYRIC = 0;
    private final static int TYPE_CUR_SINGING = 1;
    private final static int TYPE_CUR_SING = 2;
    private final static int TYPE_TOP_LINE = 3;
    private final static int TYPE_BOTTOM_LINE = 4;
    private final static int TYPE_TRANSPARENT = 5;
    private final static int TYPE_TOP_LINE_TRANSPARENT = 6;

    //当前播放进度
    private long curTime;
    //行号
    private int lineIndex;

    private int totalLines = 5;
    private int curSingLineIndex = 2;

    private Paint mPaint;
    private Paint mSingedPaint;

    private int mCurSingTxtColor;
    private int mCurSingingTxtColor;
    private int mOtherTxtColor;
    private int mOtherTxtSize = 45;
    //当前行字体大小
    private int mCurSingTxtSize = 60;

    private ILyricParser parser;
    private boolean mStop;
    private boolean mStartDarw;

    private int viewWidth;
    private int viewHeight;
    private int topSpaceing = 50;
    private int topOffset = 0;

    private long autoScrollTime = 200;

    private float mVerticalScrollOffset;
    private boolean mScrolling;

    public LyricView(Context context) {
        super(context);
        init();
    }

    public LyricView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {

        initDefaultConfig();

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mSingedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mSingedPaint.setStrokeWidth(1);
        mPaint.setStrokeWidth(1);
        setWillNotDraw(false);
        logMsg("Init");
    }

    private void initDefaultConfig() {
        mCurSingingTxtColor = Color.BLUE;
        mCurSingTxtColor = Color.WHITE;
        mOtherTxtColor = Color.WHITE;
    }

    private Paint getPaintWithType(int type) {

        switch (type) {
            case TYPE_NO_LYRIC:

                break;

            case TYPE_TOP_LINE:
            case TYPE_BOTTOM_LINE:

                mPaint.setTextSize(mOtherTxtSize);
                mPaint.setColor(mOtherTxtColor);
                break;

            case TYPE_CUR_SINGING:

                mPaint.setTextSize(mCurSingTxtSize);
                mPaint.setColor(mCurSingingTxtColor);
                break;
            case TYPE_CUR_SING:

                mPaint.setTextSize(mCurSingTxtSize);
                mPaint.setColor(mCurSingTxtColor);
                break;

            case TYPE_TOP_LINE_TRANSPARENT:

                mPaint.setColor(Color.TRANSPARENT);
                mPaint.setTextSize(mOtherTxtSize);
                break;
        }

        return mPaint;
    }

    private float measureRatioWithCurLine(float textSize) {
        return mCurSingTxtSize == 0 ? 1 : textSize / mCurSingTxtSize;
    }

    private boolean isMoveToNext() {
        List<LyricInfo> lyrics = parser.getLyrics();
        if (lineIndex < lyrics.size()) {
            if (lineIndex + 1 < lyrics.size()) {
                LyricInfo item = lyrics.get(lineIndex + 1);
                if (this.curTime >= item.startTime && this.curTime <= item.endTime) {
                    return true;
                }
            }
        }
        return false;
    }

    public void updateLyric(long curTime) {
        this.curTime = curTime;
        logMsg("UpdateLyric : " + curTime);
        invalidate();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        viewWidth = right - left;
        viewHeight = bottom - top;
    }

    private int index;
    private boolean isDraw;

    @Override
    protected void onDraw(Canvas canvas) {

        Paint p = getPaintWithType(TYPE_CUR_SINGING);
        String text = "Angeads;adsasd";
        Rect r = new Rect();
        p.getTextBounds(text, 0, text.length(), r);

        canvas.drawText(text, 0, text.length(), 100, 100, p);
        p.setColor(Color.WHITE);

        Paint.FontMetrics metrics = p.getFontMetrics();

        int width = r.width();
        int height = r.height();
//        int l = 100;
//        int r1 = l + width;
//        int bottom = 100;
//        int top = bottom - height;
        r.left = 100 +index;
        r.right = 100+width;
        r.bottom = (int) (100+metrics.bottom);
        r.top = (int) (100 + metrics.top);

        canvas.save();
        canvas.clipRect(r);
        canvas.drawText(text, 0, text.length(), 100,100, p);
        canvas.restore();
        logMsg("Size : "+ r.left+"  "+r.top+"  "+r.right+"  "+r.bottom   +"   "+ metrics.bottom +"  "+metrics.top);

        try {
            Thread.sleep(300);
            index++;
            invalidate();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        if (true) {
            return;
        }

        if (mStop || this.parser == null || this.parser.getLyrics() == null) {
            logMsg("Stop : " + mStop + "  " + (this.parser == null) + "  ");
            return;
        }

        if (mStartDarw) {

            if (this.parser.getLyrics().size() == 0) {
                drawNoLyric(canvas);
                return;
            }

            drawAll(canvas);

            if (isMoveToNext() && !mScrolling) {
                onChangeNextLine();
            }
        }
    }

    float total;

    private void onChangeNextLine() {
        logMsg("onChangeNextLine");
        LyricInfo firstData = (LyricInfo) this.parser.getLyrics().get(0);
        mScrolling = true;
        total = topSpaceing + firstData.contentHeight * measureRatioWithCurLine(getPaintWithType(TYPE_TOP_LINE).getTextSize());
        logMsg("Total : " + total);
        ValueAnimator animator = ValueAnimator.ofFloat(0, total);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mVerticalScrollOffset = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        animator.setDuration(autoScrollTime);
        animator.start();
    }

    /**
     * 绘制所有行
     *
     * @param canvas
     */
    private void drawAll(Canvas canvas) {
        List<LyricInfo> lyrics = parser.getLyrics();
        if (lineIndex >= lyrics.size()) {
            logMsg("数组越界");
            return;
        }

        long startTime = System.currentTimeMillis();
        logMsg("DrawAll : " + viewWidth + "  " + viewHeight);
        float offset = topOffset - mVerticalScrollOffset;
        LyricInfo firstData = lyrics.get(0);
        int startPosition = -1;
        float ratio = mVerticalScrollOffset / total;
        int vAlpha = (int) (255 * ratio);

        //定制多绘制最后一行
        for (int i = 0; i < totalLines + 1; i++) {
            int type = i == curSingLineIndex ? TYPE_CUR_SING : TYPE_TOP_LINE;
            Paint paint = getPaintWithType(type);

            String content = firstData.content;
            float contentWidth = firstData.contentWidth * measureRatioWithCurLine(paint.getTextSize());
            float contentHeight = firstData.contentHeight * measureRatioWithCurLine(paint.getTextSize());

            if (mScrolling) {
                //滚动的时候进行字体的缩放
                if (i == curSingLineIndex) {
                    int textSize = (int) (mCurSingTxtSize - (mCurSingTxtSize - mOtherTxtSize) * ratio);
                    paint.setTextSize(textSize);
                } else if (i == curSingLineIndex + 1) {
                    int textSize = (int) (mOtherTxtSize + (mCurSingTxtSize - mOtherTxtSize) * ratio);
                    paint.setTextSize(textSize);
                }
            }

            if (lineIndex >= curSingLineIndex) {
                int realPosition = lineIndex + i - curSingLineIndex;
                if (realPosition < lyrics.size()) {
                    LyricInfo info = lyrics.get(realPosition);
                    contentWidth = info.contentWidth * measureRatioWithCurLine(paint.getTextSize());
                    contentHeight = info.contentHeight * measureRatioWithCurLine(paint.getTextSize());
                    content = info.content;
                } else {
                    paint = getPaintWithType(TYPE_TOP_LINE_TRANSPARENT);
                }
            } else {
                if (i + lineIndex >= curSingLineIndex) {

                    if (startPosition == -1) {
                        startPosition = i;
                    }

                    int realPosition = i - startPosition;
                    if (realPosition >= 0) {
                        LyricInfo info = lyrics.get(realPosition);
                        contentWidth = info.contentWidth * measureRatioWithCurLine(paint.getTextSize());
                        contentHeight = info.contentHeight * measureRatioWithCurLine(paint.getTextSize());
                        content = info.content;
                    } else {
                        paint = getPaintWithType(TYPE_TOP_LINE_TRANSPARENT);
                    }
                } else {
                    paint = getPaintWithType(TYPE_TOP_LINE_TRANSPARENT);
                }
            }

            if (i == totalLines && !content.equals(firstData.content)) {
                //这里是最后一行，
                paint.setAlpha(vAlpha);
            }

            offset += (topSpaceing + contentHeight);
            float left = (viewWidth - contentWidth) / 2;

            if (i == curSingLineIndex) {

                if (!mScrolling) {
                    mSingedPaint.setTextSize(mCurSingTxtSize);
                    mSingedPaint.setColor(mCurSingingTxtColor);
                    mSingedPaint.setColor(mCurSingingTxtColor);
                    canvas.drawText(content, 0, content.length(), left, offset, mSingedPaint);

                    float l = 0;
                    float t = offset - contentHeight - topSpaceing;
                    float r = left + 0;
                    float b = offset;

                    canvas.clipRect(l, t, r, b);
                }

                logMsg("Paint : " + paint.getColor() + "   " + offset + "   " + left);
                canvas.drawText(content, 0, content.length(), left, offset, paint);
            } else {
                canvas.drawText(content, 0, content.length(), left, offset, paint);
            }
        }

        if (mVerticalScrollOffset == total && total > 0) {
            mScrolling = false;
            mVerticalScrollOffset = 0;
            lineIndex++;
            total = 0;
            invalidate();
        }

        long endTime = System.currentTimeMillis();
        logMsg("DrawAll耗时 : " + (endTime - startTime));
    }

    private void drawNoLyric(Canvas canvas) {
        logMsg("DrawNoLyric");
    }

    private float getPlayOffset() {
        if (!mScrolling) {
            LyricInfo item = (LyricInfo) parser.getLyrics().get(lineIndex);
            List<LyricWord> words = item.words;
            if (words != null && words.size() > 0) {
                int size = words.size();
                float len = 0;
                for (int i = 0; i < size; i++) {
                    LyricWord word = words.get(i);
                    if (this.curTime >= word.startTime && this.curTime <= word.endTime) {
                        float ratio = (this.curTime - word.startTime) / ((word.endTime - word.startTime) * 1f);
                        len += word.wordWidth * ratio;
                        break;
                    }
                    len += word.wordWidth;
                }
                return len;
            }
        }
        return 0;
    }

    @Override
    public void setNoLyricText(String hint) {

    }

    @Override
    public void setNoLyricTextColor(int color) {

    }

    @Override
    public void setNoLyricTextSize(float textSize) {

    }

    @Override
    public void setNoLyricPadding(int left, int top, int right, int bottom) {

    }

    @Override
    public void setNoLyricGravity(int gravity) {

    }

    @Override
    public void setLyricLines(int lines, int curSingLineIndex) {

        if (curSingLineIndex > lines - 1) {
            throw new IndexOutOfBoundsException("當前演唱行必須位於顯示總行大小之內,索引從0開始");
        }

        this.totalLines = lines;
        this.curSingLineIndex = curSingLineIndex;
    }

    @Override
    public void setCurSingLineTextColor(int color) {

    }

    @Override
    public void setShaDowColor(int color) {

    }

    @Override
    public void setShaDowEnabled(boolean enabled) {

    }

    @Override
    public void setScrollEnabled(boolean enabled) {

    }

    @Override
    public void setLyricParser(ILyricParser parser) {
        if (parser != null) {
            this.parser = parser;
            parser.measureTextSize(getPaintWithType(TYPE_CUR_SINGING));
        }
    }

    @Override
    public void start() {
        mStop = false;
        mStartDarw = true;
        invalidate();
    }

    @Override
    public void stop() {
        mStop = true;
        mStartDarw = false;
        invalidate();
    }

    private void logMsg(String msg) {
        Log.d(TAG, msg);
    }

    @Override
    public int getCurLineIndex() {
        return lineIndex;
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mStartDarw = false;
        mStop = false;
    }
}
